package com.todo.member.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.api.client.util.Lists;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.component.redis.RedisService;
import com.todo.member.application.convert.MemberInfoConvert;
import com.todo.member.application.entity.bo.MemberVipInfoBO;
import com.todo.member.application.service.MemberVipInfoService;
import com.todo.member.common.base.redis.MemberKeyBuild;
import com.todo.member.common.enums.MemberVipStatusEnum;
import com.todo.member.common.enums.MemberVipTypeEnum;
import com.todo.member.infrastructure.entity.po.MemberVipInfoPO;
import com.todo.member.infrastructure.repository.MemberVipInfoRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author azhebuxing
 * @date 2025/3/7 01:04
 * @description
 */
@Slf4j
@Service
public class MemberVipInfoServiceImpl implements MemberVipInfoService {

    @Resource
    private MemberVipInfoRepository memberVipInfoRepository;
    @Resource
    private RedisService redisService;


    @Override
    public Boolean insertMemberVipInfo(MemberVipInfoBO memberVipInfoBO) {
        if (memberVipInfoBO == null) {
            return null;
        }
        List<MemberVipInfoPO> sameVipCodeInfoPO = memberVipInfoRepository.queryMemberVipInfoListByVipCode(memberVipInfoBO.getVipCode());
        if (CollectionUtils.isNotEmpty(sameVipCodeInfoPO)) {
            log.error("MemberVipInfoService#insertMemberVipInfo 新增会员信息失败，存在对应vipCode信息,应该走版本更新逻辑 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "应该走版本更新逻辑");
        }
        MemberVipInfoPO sameNameInfoPO = memberVipInfoRepository.queryMemberVipInfoPOByName(memberVipInfoBO.getName());
        if (sameNameInfoPO != null) {
            log.error("MemberVipInfoService#insertMemberVipInfo 新增会员信息失败，存在对应name信息 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
            return false;
        }
        //TODO 验证特权信息是否正确

        memberVipInfoBO.setStatus(MemberVipStatusEnum.DRAFT);
        MemberVipInfoPO memberVipInfoPO = MemberInfoConvert.convertToMemberVipInfoPO(memberVipInfoBO);
        Boolean updated = memberVipInfoRepository.insertMemberVipInfoPO(memberVipInfoPO);
        if (updated) {
            String key = MemberKeyBuild.buildMemberVipInfoKey(memberVipInfoBO.getId());
            redisService.set8H(key, JSONObject.toJSONString(memberVipInfoBO));
        }

        return updated;
    }

    @Override
    public Boolean updateMemberVipInfo(MemberVipInfoBO memberVipInfoBO) {
        if (memberVipInfoBO == null || memberVipInfoBO.getId() == null) {
            return null;
        }
        MemberVipInfoBO alreadyData = queryMemberVipInfoById(memberVipInfoBO.getId());
        if (alreadyData == null) {
            log.error("MemberVipInfoService#updateMemberVipInfo 更新会员信息失败，数据为空，默认不处理 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (!memberVipInfoBO.getVipCode().equals(alreadyData.getVipCode())) {
            log.error("MemberVipInfoService#updateMemberVipInfo 更新会员信息失败，vipCode不允许更新 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "vipCode不允许更新");
        }
        if (!memberVipInfoBO.getName().equals(alreadyData.getName())) {
            MemberVipInfoPO memberVipInfoPO = memberVipInfoRepository.queryMemberVipInfoPOByName(memberVipInfoBO.getName());
            if (memberVipInfoPO != null) {
                log.error("MemberVipInfoService#updateMemberVipInfo 更新会员信息失败，存在对应name信息 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
                throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "存在对应name信息");
            }
        }


        memberVipInfoBO.setStatus(MemberVipStatusEnum.DRAFT);
        MemberVipInfoPO memberVipInfoPO = MemberInfoConvert.convertToMemberVipInfoPO(memberVipInfoBO);
        Boolean updated = memberVipInfoRepository.updateMemberVipInfoPOById(memberVipInfoPO);
        if (updated) {
            String key = MemberKeyBuild.buildMemberVipInfoKey(memberVipInfoBO.getId());
            redisService.del(key);
        }
        return updated;
    }

    @Override
    public Boolean removeMemberVipInfoById(Long id) {
        if (id == null || id <= 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        MemberVipInfoBO memberVipInfoBO = queryMemberVipInfoById(id);
        if (memberVipInfoBO == null) {
            return true;
        }
        if (memberVipInfoBO.getStatus() == MemberVipStatusEnum.RUNNING) {
            log.error("MemberVipInfoService#removeMemberVipInfoById 删除会员信息失败，存在对应running信息 memberVipInfoBO：【{}】", JSONObject.toJSONString(memberVipInfoBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "当前数据运行中");
        }
        Boolean updated = memberVipInfoRepository.removeMemberVipInfoPOById(id);
        if (updated) {
            String key = MemberKeyBuild.buildMemberVipInfoKey(memberVipInfoBO.getId());
            redisService.del(key);
        }
        return updated;
    }

    @Override
    public MemberVipInfoBO queryMemberVipInfoById(Long id) {
        if (id == null || id <= 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        String key = MemberKeyBuild.buildMemberVipInfoKey(id);
        if (redisService.hasKey(key)) {
            String value = redisService.get(key);
            return JSONObject.parseObject(value, MemberVipInfoBO.class);
        }
        MemberVipInfoPO memberVipInfoPO = memberVipInfoRepository.queryMemberVipInfoPOById(id);
        if (memberVipInfoPO == null) {
            return null;
        }
        redisService.setOneDay(key, JSONObject.toJSONString(MemberInfoConvert.convertToMemberVipInfoBO(memberVipInfoPO)));
        return MemberInfoConvert.convertToMemberVipInfoBO(memberVipInfoPO);
    }

    @Override
    public List<MemberVipInfoBO> queryVipInfoByVipCode(String vipCode) {
        if (StringUtils.isBlank(vipCode)) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        List<MemberVipInfoPO> memberVipInfoPOList = memberVipInfoRepository.queryMemberVipInfoListByVipCode(vipCode);
        if (CollectionUtils.isNotEmpty(memberVipInfoPOList)) {
            return memberVipInfoPOList.stream().map(MemberInfoConvert::convertToMemberVipInfoBO).collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MemberVipInfoBO> queryVipInfoListByVipCode(MemberVipTypeEnum vipType) {
        if (vipType == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        List<MemberVipInfoPO> memberVipInfoPOList = memberVipInfoRepository.queryMemberVipInfoListByVipType(vipType.getType());
        if (CollectionUtils.isNotEmpty(memberVipInfoPOList)) {
            return memberVipInfoPOList.stream().map(MemberInfoConvert::convertToMemberVipInfoBO).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }


    @Override
    @Transactional
    public Boolean updateMemberVipInfoStatusById(Long id, MemberVipStatusEnum oldStatus, MemberVipStatusEnum newStatus) {
        if (id == null || oldStatus == null || newStatus == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        if (oldStatus.equals(newStatus)) {
            return true;
        }
        MemberVipInfoBO memberVipInfoBO = queryMemberVipInfoById(id);
        if (memberVipInfoBO == null) {
            log.error("MemberVipInfoService#updateMemberVipInfoStatusById 更新会员信息失败，当前数据已经不存在 id:[{}],oldStatus:[{}],newStatus:[{}]", id, oldStatus, newStatus);
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST, "数据不存在");
        }
        if (newStatus.equals(memberVipInfoBO.getStatus())) {
            return true;
        }

        if (oldStatus.equals(MemberVipStatusEnum.RUNNING) && !newStatus.equals(MemberVipStatusEnum.SHUTDOWN)) {
            log.error("MemberVipInfoService#updateMemberVipInfoStatusById 更新会员信息失败，当前状态不允许操作 id:[{}],oldStatus:[{}],newStatus:[{}]", id, oldStatus, newStatus);
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "当前状态不允许操作");
        }

        //新状态为运行中，将老数据至为停止
        if (newStatus.equals(MemberVipStatusEnum.RUNNING)) {
            MemberVipInfoPO memberVipInfoPO = memberVipInfoRepository.queryEffectiveMemberVipInfoByVipType(memberVipInfoBO.getVipType().getType());
            if (memberVipInfoPO != null) {
                Boolean updatedRunningData = memberVipInfoRepository.updateMemberVipInfoStatusById(memberVipInfoPO.getId(), MemberVipStatusEnum.RUNNING, MemberVipStatusEnum.SHUTDOWN);
                if (!updatedRunningData) {
                    throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "更新失败");
                }
                String key = MemberKeyBuild.buildMemberVipInfoKey(memberVipInfoPO.getId());
                redisService.del(key);
            }
        }


        Boolean updated = memberVipInfoRepository.updateMemberVipInfoStatusById(id, oldStatus, newStatus);
        if (!updated) {
            return false;
        }
        //运行中状态，则需要调整运行中缓存数据
        if (newStatus.equals(MemberVipStatusEnum.RUNNING) || oldStatus.equals(MemberVipStatusEnum.RUNNING)) {
            String effectiveKey = MemberKeyBuild.buildEffectiveMemberVipInfoList();
            redisService.del(effectiveKey);
        }
        String key = MemberKeyBuild.buildMemberVipInfoKey(memberVipInfoBO.getId());
        redisService.del(key);
        return true;
    }

    @Override
    public List<MemberVipInfoBO> queryEffectiveMemberVipInfoList() {
        String effectiveKey = MemberKeyBuild.buildEffectiveMemberVipInfoList();
        if (redisService.hasKey(effectiveKey)) {
            List<String> stringList = redisService.lRange(effectiveKey, 0, -1);
            if (CollectionUtils.isNotEmpty(stringList)) {
                List<MemberVipInfoBO> memberVipInfoBOList = stringList.stream().map(s -> JSONObject.parseObject(s, MemberVipInfoBO.class)).collect(Collectors.toList());
                return memberVipInfoBOList;
            }
        }
        List<MemberVipInfoPO> memberVipInfoPOList = memberVipInfoRepository.queryEffectiveMemberVipInfoList();
        if (CollectionUtils.isNotEmpty(memberVipInfoPOList)) {
            List<MemberVipInfoBO> memberVipInfoBOList = memberVipInfoPOList.stream().map(MemberInfoConvert::convertToMemberVipInfoBO).collect(Collectors.toList());
            for (MemberVipInfoBO item : memberVipInfoBOList) {
                redisService.lPush(effectiveKey, JSONObject.toJSONString(item));
            }
        }
        return Collections.emptyList();
    }
}
